package cas.client;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

@WebFilter(filterName = "UserAuthenticationFilter", urlPatterns = {"/main-page"})
public class UserAuthenticationFilter implements Filter {

    private static final String CAS_NAME = "http://localhost:8080";

    // 确保请求参数中有token，或者session中有token
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String tokenInParameter = request.getParameter("token");
        if (tokenInParameter == null) {
            // 请求参数中没有token
            String tokenInSession = (String) request.getSession().getAttribute("token");
            if (tokenInSession == null) {
                // session中也没有token
                redirectToLogin(request, response);
            } else {
                // session中有token
                authenticateToken(servletRequest, servletResponse, filterChain, tokenInSession);
            }
        } else {
            // 请求参数中有token
            authenticateToken(servletRequest, servletResponse, filterChain, tokenInParameter);
        }
    }

    // 重定向到CAS登录页面
    private static void redirectToLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        StringBuffer url = request.getRequestURL();
        String returnAddress = URLEncoder.encode(url.toString(), "UTF-8");
        response.sendRedirect(CAS_NAME + "/login-page?return-address=" + returnAddress);
    }

    // 请求CAS验证token，获取用户信息
    private static void authenticateToken(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain, String token) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        User user;
        try {
            // 请求CAS进行验证
            user = requestCAS(token);
        } catch (IOException e) {
            // 请求CAS验证失败
            redirectToLogin(request, response);
            return;
        }
        if (user == null) {
            // token无效
            redirectToLogin(request, response);
        } else {
            // token有效
            // 创建session，放入user和token
            request.getSession().setAttribute("user", user);
            request.getSession().setAttribute("token", token);
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    // 向CAS发送请求
    private static User requestCAS(String token) throws IOException {
        URL url = new URL(CAS_NAME + "/user-info-api");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("Accept-Charset", "UTF-8");
        conn.setRequestProperty("Authorization", token);
        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(conn.getInputStream(), User.class);
        conn.disconnect();
        return user;
    }

}
